// clss类
// class person{
//  age:number
//  gender='男'
// }
// const p=new person()

// 构造函数
class Person {
    age:number
    gender:string
    sex='男'
    // 构造函数为成员属性赋初值
    // 构造函数没有返回值，不需要我们添加返回值类型
    constructor(age:number,gender:string){
        this.age=age
        this.gender=gender
    }
}

const P=new Person(18,'男')
console.log(P.age,P.gender,P.sex);

// 实例方法的使用
class Point{
    x=1
    y=2
    say(n:number){
        this.x*=n
        this.y*=n
    }
} 

const point=new Point()
point.say(2)
console.log(point.x,point.y);

// 类的继承

// extends方式实现
class Animal{
    move(){
        console.log('moving along');
    }
}
class Dog extends Animal{
    bark(){
        console.log('汪');
        
    }
}
const d=new Dog()
d.move()
// implements（实现接口）
// 用implements实现一个接口里的类型，使用了implements的这个类必须要有他里面的属性
interface Singable{
    sing():void
}
 class PPerson implements Singable {
    sing(){
        console.log('你是我的小啊小苹果');
        
    }
 }
//  readonly修饰符 规定属性为只读,只能被构造函数赋值
class Read{
    readonly age:number=18//设置的初始值
    constructor(n?:number){
       if(n){
        this.age=n
       }else{return}

    }
//     nihao(n:number){
//         this.age=n  //报错，他只是一个只读项
//     }
}
const only= new Read(20) 
// 在对象和接口中同样可以使用readonly
interface o{
   readonly age:number
}

let obj:o={
age:18
}
// 或则直接在对象类型中使用
let jj:{readonly age:number}={
    age:125
}
// 两个类的兼容性演示
class one{
    x:number
    y:number
}
class one1{
    x:number
    y:number
    z:number
}
const y:one=new one1() //两者的结构类型是一样的
// one1的成员至少要与one的相同才行,只能是多的给少的赋值

// 接口也可以进行兼容
interface h1{
    a:number
    b:number
}
interface h2{
    a:number
    b:number
}
interface h3{
    a:number
    b:number
    c:number
}
let d1: h1
let d2: h2
let d3: h3={a:1,b:2,c:3}

d1=d3

 class PD{
    a:number
    b:number
    c:number
 }
//  可以将类兼容给接口
 d2=new PD()

//  函数的兼容性
// 参数个数的兼容性,多的兼容少的
type F1=(a:number)=>void
type F2=(a:number,b:number)=>void
let f1:F1=function(){}
let f2:F2
f2 = f1

// 参数类型
interface Point2D{x:number,y:number}
interface Point3D{x:number,y:number,z:number}
type D2=(p:Point2D)=>void  //相当于有两个参数
type D3=(p:Point3D)=>void  //相当于有三个参数

let I2:D2
let I3:D3
// 将对象拆开，看成是一个个参数，因为这是函数的兼容，多的兼容少的

// 返回值类型，只需要关注返回值类型的本身即可
// 原始类型 
type F5=()=>string
type F6=()=>string
// 这时 两者是可以相互兼容的

// 对象类型
type F7=()=>{name:string}
type F8=()=>{name:string;age:number}

// 这时少的兼容多的